package com.zxl.gtion.controller;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zxl.gtion.entity.Hospital;
import com.zxl.gtion.entity.HospitalComment;
import com.zxl.gtion.entity.User;
import com.zxl.gtion.enums.RedisEnums;
import com.zxl.gtion.pojo.HospitalInfo;
import com.zxl.gtion.service.HospitalCommentService;
import com.zxl.gtion.service.HospitalService;
import com.zxl.gtion.util.R;
import com.zxl.gtion.util.ShiroUtils;
import com.zxl.gtion.vo.HospitalVO;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * (Hospital)表控制层
 *
 * @author 
 * @since 2024-03-06 16:44:24
 */
@RestController
@RequestMapping("hospital")
@RequiredArgsConstructor
public class HospitalController  {
    /**
     * 服务对象
     */
    private final HospitalService hospitalService;
    private final HospitalCommentService commentService;
    private final StringRedisTemplate redisTemplate;

    @GetMapping("getHospitals")
    @ApiOperation("根据经纬度获取多少km内的医院数据及其评论")
    public R<List<HospitalVO>> getHospitals() {
        String lon = "113.593202";
        String la = "23.562861";
        // 通过geo.radius 根据经纬度获取该经纬度附近附近多少km 的医院信息
        GeoResults<RedisGeoCommands.GeoLocation<String>> radius = redisTemplate.opsForGeo()
                .radius(RedisEnums.GEO_HOSPITAL.getValue(),
                new Circle(
                        new Point(Double.parseDouble(lon), Double.parseDouble(la)),
                        new Distance(5000, Metrics.KILOMETERS)
                ),
                        // radius这个方法加上这段才能找到对应的经纬度信息，不然只能查到name信息
                        RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeCoordinates().includeDistance());
        if (radius == null) {
            return R.ok(new ArrayList<>());
        }
        List<GeoResult<RedisGeoCommands.GeoLocation<String>>> content = radius.getContent();
        List<HospitalVO> hospitalVOS = new ArrayList<>();
        HospitalVO hospitalVO;
        // 拿到医院信息并将其转为HospitalVO数据类型
        for (GeoResult<RedisGeoCommands.GeoLocation<String>> geoLocationGeoResult : content) {
            RedisGeoCommands.GeoLocation<String> content1 = geoLocationGeoResult.getContent();
            // 因为存的是直接存的id值 所以name就是对应hospital的id
            String id = content1.getName();
            // 一开始查询的只有地址信息 没有具体的信息 比如名字等。 所以要再查一次获取信息然后存到HospitalVO对象里面
            Hospital hospital = hospitalService.getById(id);
            hospitalVO = BeanUtil.copyProperties(hospital, HospitalVO.class);
            hospitalVO.setId(Integer.parseInt(id));
            hospitalVO.setLa(Double.toString(content1.getPoint().getY()));
            hospitalVO.setLon(Double.toString(content1.getPoint().getX()));
            hospitalVO.setDis(geoLocationGeoResult.getDistance().getValue());

            // 获取评论信息
            List<HospitalComment> list = commentService.lambdaQuery().eq(HospitalComment::getHospitalId, id).list();
            if (!list.isEmpty()) {
                hospitalVO.setComments(list);
            }
            hospitalVOS.add(hospitalVO);
        }

        return R.ok(hospitalVOS);
    }


    @PostMapping("insertHospitalComment")
    @ApiOperation("新增医院评论")
    public R<Boolean> insertHospitalComment(@RequestBody HospitalComment comment) {
        User userInfo = ShiroUtils.getUserInfo();
        if (userInfo == null) {
            comment.setUserId(1);
            comment.setImgUrl("https://thirdwx.qlogo.cn/mmopen/vi_32/POgEwh4mIHO4nibH0KlMECNjjGxQUq24ZEaGT4poC6icRiccVGKSyXwibcPq4BWmiaIGuG1icwxaQX6grC9VemZoJ8rg/132");
            comment.setUserNickName("匿名用户");
        } else {
            comment.setUserId(userInfo.getId());
            comment.setImgUrl(userInfo.getHeadImg());
            comment.setUserNickName(userInfo.getNickName());
        }
        return R.ok(commentService.save(comment));
    }

    @GetMapping("getCommentByHosId")
    @ApiOperation("根据医院id获取医院评论信息")
    public R<List<HospitalComment>> getCommentByHosId(@RequestParam String id) {
        return R.ok(commentService.lambdaQuery().eq(HospitalComment::getHospitalId, id).list());
    }

    @PostMapping("insertDefaultHospital")
    @ApiOperation("新增从化区默认医院信息")
    public R insertDefaultHospital(@RequestBody List<HospitalInfo> hospitalInfoList) {
//        this.hospitalService.save(hospital);
//        Integer id = hospital.getId();
//        String la = hospital.getLa();
//        String lon = hospital.getLon();
        List<Hospital> hospitals = new ArrayList<>();
        Hospital hospital;
        String lon = "";
        String la = "";
        for (HospitalInfo hospitalInfo : hospitalInfoList) {
            String location = hospitalInfo.getLocation();
            List<String> lonAndLa = Arrays.stream(location.split(",")).collect(Collectors.toList());
            lon = lonAndLa.get(0);
            la = lonAndLa.get(1);
            List<HospitalInfo.Photo> photos = hospitalInfo.getPhotos();
            String imgUrl = "";
            if (!photos.isEmpty()) {
                imgUrl = photos.get(0).getUrl();
            }
            hospital = new Hospital();
            hospital.setLa(la);
            hospital.setLon(lon);
            hospital.setImg(imgUrl);
            hospital.setName(hospitalInfo.getName());
            hospital.setAddress(hospitalInfo.getAddress());
            String tel = hospitalInfo.getTel();
            List<String> collect = Arrays.stream(tel.split(",")).collect(Collectors.toList());
            if (!collect.isEmpty()) {
                hospital.setPhone(collect.get(0));
            }
            hospital.setIntroduce(hospitalInfo.getType());
            hospitalService.save(hospital);
            redisTemplate.opsForGeo().add(RedisEnums.GEO_HOSPITAL.getValue(),
                    new Point(Double.parseDouble(lon), Double.parseDouble(la)),
                    hospital.getId().toString());
        }

        return R.ok();
    }

    @PostMapping("insertHospital")
    @ApiOperation("新增医院数据")
    public R insertHospital(@RequestBody @Validated Hospital hospital) {
        this.hospitalService.save(hospital);
        Integer id = hospital.getId();
        String la = hospital.getLa();
        String lon = hospital.getLon();
        redisTemplate.opsForGeo().add(RedisEnums.GEO_HOSPITAL.getValue(),
                new Point(Double.parseDouble(lon), Double.parseDouble(la)),
                id.toString());
        return R.ok();
    }


    /**
     * 分页查询所有数据
     *
     * @param page 分页对象
     * @param hospital 查询实体
     * @return 所有数据
     */
    @GetMapping
    public R selectAll(Page<Hospital> page, Hospital hospital) {
        return R.ok(this.hospitalService.page(page, new QueryWrapper<>(hospital)));
    }

    /**
     * 通过主键查询单条数据
     *
     * @param id 主键
     * @return 单条数据
     */
    @GetMapping("{id}")
    public R selectOne(@PathVariable Serializable id) {
        return R.ok(this.hospitalService.getById(id));
    }

    /**
     * 新增数据
     *
     * @param hospital 实体对象
     * @return 新增结果
     */
    @PostMapping
    public R insert(@RequestBody Hospital hospital) {
        return R.ok(this.hospitalService.save(hospital));
    }

    /**
     * 修改数据
     *
     * @param hospital 实体对象
     * @return 修改结果
     */
    @PutMapping
    public R update(@RequestBody Hospital hospital) {
        return R.ok(this.hospitalService.updateById(hospital));
    }

    /**
     * 删除数据
     *
     * @param idList 主键结合
     * @return 删除结果
     */
    @DeleteMapping
    public R delete(@RequestParam("idList") List<Long> idList) {
        return R.ok(this.hospitalService.removeByIds(idList));
    }
}

